from algorithms.algorithm import Algorithm
from websocket.msghandler import MsgContext, MessageType


class SimpleTaskHandler:
    indicator_data = None

    @classmethod
    def handle(cls, message):
        Algorithm.simple_callback = cls.simple_callback
        algorithms_data, problem_data, indicator_data, max_fun_eval, obj_dim, pop_size, run_size, save_size, \
            var_dim = cls.init(message)
        cls.indicator_data = indicator_data
        problem_class = MsgContext.get_cls_by_str(problem_data['cls'])
        problem_obj = problem_class(var_dim, obj_dim, max_fun_eval, problem_data['params'])
        MsgContext.simple_problem_objs.append(problem_obj)
        algorithm_class = MsgContext.get_cls_by_str(algorithms_data['cls'])
        algorithm_obj = algorithm_class(problem_obj, pop_size, algorithms_data['params'])
        algorithm_obj.run(is_save_data=False)
        MsgContext.task_complete_return(MessageType.SIMPLE_TASK_COMPLETED)

    @staticmethod
    def init(message):
        algorithms_datas, problem_datas, form_data, indicator_data, _ = MsgContext.get_data(message)
        max_fun_eval, obj_dim, pop_size, run_size, save_size, var_dim = MsgContext.get_form_data(form_data)
        return algorithms_datas[0], problem_datas[0], indicator_data, max_fun_eval, obj_dim, pop_size, run_size, \
            save_size, var_dim

    @classmethod
    def simple_callback(cls, pop, problem_obj, FE):
        indicator_name = cls.indicator_data['name']
        if indicator_name == 'obj' or indicator_name == 'dec':
            MsgContext.callback({
                'messageType': MessageType.SIMPLE_TASK_MSG.value,
                'indicator_value': [FE, pop[indicator_name].tolist()]
            })
            return
        indicator_class = MsgContext.get_cls_by_str(cls.indicator_data['cls'])
        indicator_value = indicator_class.get_value(pop, problem_obj)
        MsgContext.callback({
            'messageType': MessageType.SIMPLE_TASK_MSG.value,
            'indicator_value': [FE, indicator_value],
        })
